package com.customize.cas;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.crypto.password.PasswordEncoder;

import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * @author Leighton
 * @create 2018-11-09.
 * 自定义密码验证
 *  https://apereo.github.io/cas/5.3.x/installation/Configuration-Properties-Common.html#password-encoding
 * CAS在身份验证处理,基本都是基于Spring Security对密码编码,
 * 如果您计划设计自己的密码编码器或编写脚本来执行此操作，则可能还需要确保覆盖在运行时具有以spring-security-core模块
 * 官方实例中通过继承AbstractPasswordEncoder类来实现，通过观察AbstractPasswordEncoder的源码发现这个抽象类实现了
 *PasswordEncoder接口，实现任意个都可以，且内部有encode重载方法，返回一个String，一个返回byte[]类型。
 * 还有一个matches返回对比结果。下面是我们实现PasswordEncoder并重写encode和matches方法。
 */
public class CustomPasswordEncoder implements PasswordEncoder {
    private static Logger logger= LoggerFactory.getLogger(CustomPasswordEncoder.class);

    /**
     * 对密码进行加密
     * @param charSequence
     * @return
     */
    @Override
    public String encode(CharSequence charSequence) {
        try {
            //对数据进行md5加密
            MessageDigest md=MessageDigest.getInstance("MD5");
            md.update(charSequence.toString().getBytes());
            String pwd=new BigInteger(1,md.digest()).toString(16);
            logger.info("encode方法：加密前（ {} ），加密后（ {} ）",charSequence,pwd);
            return pwd;
        } catch (NoSuchAlgorithmException e) {
           logger.error("对密码进行md5异常",e);
        }
        return null;
    }

    /**
     * 判断密码是否匹配
     * @param rawPassword
     * @param encodedPassword
     * @return
     */
    @Override
    public boolean matches(CharSequence rawPassword, String encodedPassword) {
        //判断密码为空返回fasle
        if (StringUtils.isBlank(rawPassword)){
            return false;
        }
        //调用上面的encode 对请求密码进行md5处理
        String pass=this.encode(rawPassword.toString());
        logger.info("matches方法：请求密码为：{} ，数据库密码为：{}，加密后的请求密码为：{}",rawPassword,encodedPassword,pass);
        //比较密码是否一致
        return pass.equals(encodedPassword);
    }
}
